import json  # 导入json模块，用于处理json格式的数据
import os  # 导入os模块，用于进行文件和操作系统相关的操作
from datetime import datetime  # 从datetime模块中导入datetime类，用于处理日期和时间

# 定义存储用户、房间和管理员信息的文件名常量
USERS_FILE = 'users.txt'
ROOMS_FILE = 'rooms.txt'
ADMIN_FILE = 'admin.txt'

# 初始化数据函数，用于创建存储用户、房间和管理员信息的文件
def init_data():
    if not os.path.exists(USERS_FILE):  # 如果用户信息文件不存在
        with open(USERS_FILE, 'w') as f:  # 创建一个空的用户信息文件
            json.dump([], f)  # 写入一个空的列表到文件中，表示没有用户信息
    if not os.path.exists(ROOMS_FILE):  # 如果房间信息文件不存在
        with open(ROOMS_FILE, 'w') as f:  # 创建一个空的房间信息文件
            json.dump([], f)  # 写入一个空的列表到文件中，表示没有房间信息
    if not os.path.exists(ADMIN_FILE):  # 如果管理员信息文件不存在
        with open(ADMIN_FILE, 'w') as f:  # 创建一个默认的管理员信息文件
            admin = {'admin_id': 'admin', 'password': 'admin'}  # 定义默认管理员的ID和密码
            json.dump([admin], f)  # 写入管理员信息到文件中

# 读取数据函数，用于从指定文件中读取json数据并返回
def read_data(filename):
    with open(filename, 'r') as f:  # 打开指定的文件进行读取操作
        return json.load(f)  # 读取文件中的json数据并返回

# 写入数据函数，用于将json数据写入到指定文件中
def write_data(filename, data):
    with open(filename, 'w') as f:  # 打开指定的文件进行写入操作
        json.dump(data, f)  # 将数据以json格式写入文件中

# 打印标题函数，用于打印格式化的标题
def print_header(title):
    print("=" * 50)  # 打印50个等号，用于分隔标题
    print(f"{title:^50}")  # 打印居中的标题，宽度为50个字符
    print("=" * 50)  # 再次打印50个等号，用于分隔标题

# 打印菜单函数，用于打印格式化的菜单选项
def print_menu(options):
    # 枚举菜单选项，并打印每个选项的序号和内容
    print("\n".join(f"{i+1}. {option}" for i, option in enumerate(options)))
    print("=" * 50)  # 打印50个等号，用于分隔菜单

# 用户注册函数，用于注册新用户
def register_user():
    print_header("用户注册")  # 打印“用户注册”标题
    users = read_data(USERS_FILE)  # 读取现有的用户信息
    user_id = input("请输入ID: ")  # 提示用户输入ID
    name = input("请输入姓名: ")  # 提示用户输入姓名
    phone = input("请输入电话: ")  # 提示用户输入电话
    id_card = input("请输入身份证号码: ")  # 提示用户输入身份证号码
    password = input("请输入密码: ")  # 提示用户输入密码
    # 创建一个用户信息字典
    user = {
        'ID': user_id,
        '姓名': name,
        '电话': phone,
        '身份证号码': id_card,
        '状态': '未入住',
        '房间号': '',
        '总费用': 0,
        '待支付金额': 0,
        '密码': password
    }
    users.append(user)  # 将新用户信息添加到用户列表中
    write_data(USERS_FILE, users)  # 将更新后的用户信息写入文件
    print("注册成功！")  # 提示注册成功

# 用户登录函数，用于用户登录
def login_user():
    print_header("用户登录")  # 打印“用户登录”标题
    users = read_data(USERS_FILE)  # 读取现有的用户信息
    user_id = input("请输入ID: ")  # 提示用户输入ID
    password = input("请输入密码: ")  # 提示用户输入密码
    # 遍历用户列表，检查用户ID和密码是否匹配
    for user in users:
        if user['ID'] == user_id and user['密码'] == password:
            print("登录成功！")  # 提示登录成功
            return user  # 返回匹配的用户信息
    print("登录失败！")  # 提示登录失败
    return None  # 返回None表示登录失败

# 管理员注册函数，用于注册新管理员
def register_admin():
    print_header("管理员注册")  # 打印“管理员注册”标题
    admins = read_data(ADMIN_FILE)  # 读取现有的管理员信息
    admin_id = input("请输入管理员ID: ")  # 提示管理员输入ID
    password = input("请输入管理员密码: ")  # 提示管理员输入密码
    # 创建一个管理员信息字典
    admin = {
        'admin_id': admin_id,
        'password': password
    }
    admins.append(admin)  # 将新管理员信息添加到管理员列表中
    write_data(ADMIN_FILE, admins)  # 将更新后的管理员信息写入文件
    print("管理员注册成功！")  # 提示注册成功

# 管理员登录函数，用于管理员登录
def login_admin():
    print_header("管理员登录")  # 打印“管理员登录”标题
    admin_id = input("请输入管理员ID: ")  # 提示管理员输入ID
    password = input("请输入管理员密码: ")  # 提示管理员输入密码
    admins = read_data(ADMIN_FILE)  # 读取现有的管理员信息
    # 遍历管理员列表，检查管理员ID和密码是否匹配
    for admin in admins:
        if admin['admin_id'] == admin_id and admin['password'] == password:
            print("管理员登录成功！")  # 提示登录成功
            return True  # 返回True表示登录成功
    print("管理员登录失败！")  # 提示登录失败
    return False  # 返回False表示登录失败

# 增加房间函数，用于增加新的房间
def add_room():
    print_header("增加房间")  # 打印“增加房间”标题
    rooms = read_data(ROOMS_FILE)  # 读取现有的房间信息
    room_number = input("请输入房间号: ")  # 提示输入房间号
    room_name = input("请输入房间名称: ")  # 提示输入房间名称
    room_type = input("请输入房间规格: ")  # 提示输入房间规格
    room_price = float(input("请输入房间价格: "))  # 提示输入房间价格，并转换为浮点数
    # 创建一个房间信息字典
    room = {
        '房间号': room_number,
        '房间名称': room_name,
        '房间规格': room_type,
        '房间价格': room_price,
        '房间状态': '未入住'
    }
    rooms.append(room)  # 将新房间信息添加到房间列表中
    write_data(ROOMS_FILE, rooms)  # 将更新后的房间信息写入文件
    print("增加房间成功！")  # 提示增加成功

# 删除房间函数，用于删除指定的房间
def delete_room():
    print_header("删除房间")  # 打印“删除房间”标题
    rooms = read_data(ROOMS_FILE)  # 读取现有的房间信息
    room_number = input("请输入要删除的房间号: ")  # 提示输入要删除的房间号
    # 使用列表推导式过滤掉要删除的房间，并更新房间信息列表
    rooms = [room for room in rooms if room['房间号'] != room_number]
    write_data(ROOMS_FILE, rooms)  # 将更新后的房间信息写入文件
    print("删除房间成功！")  # 提示删除成功

# 修改房间函数，用于修改指定的房间信息
def modify_room():
    print_header("修改房间")  # 打印“修改房间”标题
    rooms = read_data(ROOMS_FILE)  # 读取现有的房间信息
    room_number = input("请输入要修改的房间号: ")  # 提示输入要修改的房间号
    # 遍历房间列表，查找要修改的房间
    for room in rooms:
        if room['房间号'] == room_number:
            room['房间名称'] = input("请输入新的房间名称: ")  # 提示输入新的房间名称
            room['房间规格'] = input("请输入新的房间规格: ")  # 提示输入新的房间规格
            room['房间价格'] = float(input("请输入新的房间价格: "))  # 提示输入新的房间价格，并转换为浮点数
            room['房间状态'] = input("请输入新的房间状态: ")  # 提示输入新的房间状态
            write_data(ROOMS_FILE, rooms)  # 将更新后的房间信息写入文件
            print("修改房间成功！")  # 提示修改成功
            return
    print("房间未找到！")  # 提示房间未找到

# 查询房间函数，用于查询所有房间信息
def query_room():
    print_header("查询房间")  # 打印“查询房间”标题
    rooms = read_data(ROOMS_FILE)  # 读取现有的房间信息
    # 遍历房间列表并打印房间信息
    for room in rooms:
        print(room)

# 排序房间函数，用于按房间号对房间进行排序
def sort_rooms():
    print_header("排序房间")  # 打印“排序房间”标题
    rooms = read_data(ROOMS_FILE)  # 读取现有的房间信息
    rooms.sort(key=lambda x: x['房间号'])  # 使用lambda表达式对房间列表进行排序
    write_data(ROOMS_FILE, rooms)  # 将排序后的房间信息写入文件
    print("房间排序成功！")  # 提示排序成功

# 办理入住函数，用于用户办理入住手续
def check_in(user):
    print_header("办理入住")  # 打印“办理入住”标题
    rooms = read_data(ROOMS_FILE)  # 读取现有的房间信息
    print("可入住房间列表：")  # 提示显示可入住的房间列表
    available_rooms = [room for room in rooms if room['房间状态'] == '未入住']  # 使用列表推导式过滤出未入住的房间
    for room in available_rooms:  # 遍历可入住房间列表并打印房间信息
        print(room)
    room_number = input("请输入要入住的房间号: ")  # 提示输入要入住的房间号
    for room in rooms:  # 遍历房间列表，找到要入住的房间并进行入住处理
        if room['房间号'] == room_number and room['房间状态'] == '未入住':
            check_in_time = input("请输入入住时间（格式：YYYY-MM-DD HH:MM:SS）: ")  # 提示输入入住时间
            room['房间状态'] = '已入住'  # 更新房间状态为已入住
            user['房间号'] = room_number  # 更新用户的房间号
            user['状态'] = '已入住'  # 更新用户的状态为已入住
            user['入住时间'] = check_in_time  # 更新用户的入住时间
            write_data(ROOMS_FILE, rooms)  # 将更新后的房间信息写入文件
            users = read_data(USERS_FILE)  # 读取现有的用户信息
            for u in users:  # 遍历用户列表，找到当前用户并更新信息
                if u['ID'] == user['ID']:
                    u.update(user)  # 更新用户信息
                    break
            write_data(USERS_FILE, users)  # 将更新后的用户信息写入文件
            print("办理入住成功！")  # 提示办理入住成功
            return
    print("房间不可用或不存在！")  # 提示房间不可用或不存在

# 办理退房函数，用于用户办理退房手续
def check_out(user):
    print_header("办理退房")  # 打印“办理退房”标题
    rooms = read_data(ROOMS_FILE)  # 读取现有的房间信息
    if user['房间号'] == '':  # 如果用户没有办理入住
        print("您没有办理入住！")  # 提示用户没有办理入住
        return
    check_out_time = input("请输入退房时间（格式：YYYY-MM-DD HH:MM:SS）: ")  # 提示输入退房时间
    check_in_time = datetime.strptime(user['入住时间'], '%Y-%m-%d %H:%M:%S')  # 将用户的入住时间字符串转换为datetime格式
    check_out_time = datetime.strptime(check_out_time, '%Y-%m-%d %H:%M:%S')  # 将退房时间字符串转换为datetime格式
    total_time = (check_out_time - check_in_time).total_seconds() / 3600  # 计算入住时间长度（单位：小时）
    room_price = 0  # 初始化房间价格
    for room in rooms:  # 遍历房间列表，找到用户入住的房间
        if room['房间号'] == user['房间号']:
            room_price = room['房间价格']  # 获取房间价格
            room['房间状态'] = '未入住'  # 更新房间状态为未入住
            user['房间号'] = ''  # 清空用户的房间号
            user['状态'] = '未入住'  # 更新用户的状态为未入住
            write_data(ROOMS_FILE, rooms)  # 将更新后的房间信息写入文件
            break
    total_cost = total_time * room_price  # 计算总费用
    user['总费用'] += total_cost  # 更新用户的总费用
    user['待支付金额'] += total_cost  # 更新用户的待支付金额
    user['入住时间'] = ''  # 清空用户的入住时间
    users = read_data(USERS_FILE)  # 读取现有的用户信息
    for u in users:  # 遍历用户列表，找到当前用户并更新信息
        if u['ID'] == user['ID']:
            u.update(user)  # 更新用户信息
            break
    write_data(USERS_FILE, users)  # 将更新后的用户信息写入文件
    print(f"退房成功！共消费{total_cost}元，入住时间为{total_time:.2f}小时。")  # 提示退房成功，并显示消费金额和入住时间

# 支付费用函数，用于用户支付费用
def make_payment(user):
    print_header("支付费用")  # 打印“支付费用”标题
    amount = float(input("请输入支付金额: "))  # 提示输入支付金额，并转换为浮点数
    if amount > user['待支付金额']:  # 检查支付金额是否超过待支付金额
        print("支付金额超过待支付金额！")  # 提示支付金额超过待支付金额
        return
    user['待支付金额'] -= amount  # 更新用户的待支付金额
    users = read_data(USERS_FILE)  # 读取现有的用户信息
    for u in users:  # 遍历用户列表，找到当前用户并更新信息
        if u['ID'] == user['ID']:
            u.update(user)  # 更新用户信息
            break
    write_data(USERS_FILE, users)  # 将更新后的用户信息写入文件
    print("支付成功！")  # 提示支付成功
    # 打印用户的总费用、已支付费用和待支付金额
    print(f"您的总费用为：{user['总费用']}元，已支付的费用为：{user['总费用'] - user['待支付金额']}元，当前您还需要缴纳的金额为：{user['待支付金额']}元。")

# 查看个人信息函数，用于查看当前用户的个人信息
def view_personal_info(user):
    print_header("个人信息")  # 打印“个人信息”标题
    print("个人信息如下：")  # 提示显示个人信息
    for key, value in user.items():  # 遍历用户的信息并打印
        if key != '密码':  # 排除密码信息
            print(f"{key}: {value}")

# 查看所有用户信息函数，用于查看所有用户的信息
def view_all_users():
    print_header("所有用户信息")  # 打印“所有用户信息”标题
    users = read_data(USERS_FILE)  # 读取现有的用户信息
    print("所有用户信息如下：")  # 提示显示所有用户信息
    for user in users:  # 遍历用户信息列表并打印每个用户的信息
        for key, value in user.items():
            if key != '密码':  # 排除密码信息
                print(f"{key}: {value}")
        print("----------")  # 分隔不同用户的信息

# 管理员界面函数，用于处理管理员的操作
def admin_interface():
    while True:  # 无限循环，直到管理员选择退出
        print_header("管理员界面")  # 打印“管理员界面”标题
        print_menu(["增加房间", "删除房间", "修改房间", "查询房间", "排序房间", "查看所有用户信息", "返回登录页"])  # 打印管理员操作菜单
        choice = input("请选择操作: ")  # 提示管理员选择操作
        if choice == '1':
            add_room()  # 选择增加房间
        elif choice == '2':
            delete_room()  # 选择删除房间
        elif choice == '3':
            modify_room()  # 选择修改房间
        elif choice == '4':
            query_room()  # 选择查询房间
        elif choice == '5':
            sort_rooms()  # 选择排序房间
        elif choice == '6':
            view_all_users()  # 选择查看所有用户信息
        elif choice == '7':
            break  # 返回登录页，退出循环
        else:
            print("无效选择，请重新选择！")  # 提示无效选择

# 用户界面函数，用于处理用户的操作
def user_interface(user):
    while True:  # 无限循环，直到用户选择退出
        print_header("用户界面")  # 打印“用户界面”标题
        print_menu(["办理入住", "退房", "支付", "查看个人信息", "返回登录页"])  # 打印用户操作菜单
        choice = input("请选择操作: ")  # 提示用户选择操作
        if choice == '1':
            check_in(user)  # 选择办理入住
        elif choice == '2':
            check_out(user)  # 选择退房
        elif choice == '3':
            make_payment(user)  # 选择支付费用
        elif choice == '4':
            view_personal_info(user)  # 选择查看个人信息
        elif choice == '5':
            break  # 返回登录页，退出循环
        else:
            print("无效选择，请重新选择！")  # 提示无效选择

# 主函数，用于运行旅店登记系统
def main():
    init_data()  # 初始化数据
    while True:  # 无限循环，直到用户选择退出
        print_header("旅店登记系统")  # 打印“旅店登记系统”标题
        print_menu(["用户", "管理员", "退出"])  # 打印系统操作菜单
        choice = input("请选择操作: ")  # 提示用户选择操作
        if choice == '1':
            print_menu(["用户注册", "用户登录"])  # 打印用户操作菜单
            user_choice = input("请选择操作: ")  # 提示用户选择操作
            if user_choice == '1':
                register_user()  # 选择用户注册
            elif user_choice == '2':
                user = login_user()  # 选择用户登录
                if user:
                    user_interface(user)  # 用户登录成功后进入用户界面
        elif choice == '2':
            print_menu(["管理员注册", "管理员登录"])  # 打印管理员操作菜单
            admin_choice = input("请选择操作: ")  # 提示管理员选择操作
            if admin_choice == '1':
                register_admin()  # 选择管理员注册
            elif admin_choice == '2':
                if login_admin():
                    admin_interface()  # 管理员登录成功后进入管理员界面
        elif choice == '3':
            print("感谢使用，再见！")  # 提示用户退出系统
            break  # 退出循环
        else:
            print("无效选择，请重新选择！")  # 提示无效选择

# 如果该模块是主模块，则执行main函数
if __name__ == "__main__":
    main()
